﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MoPhongLapLich
{
    class Cpu : IAddQueue,IRunable
    {
        private readonly int _q;
        private int _time;
        private LinkedList<Process> _processes;
        private List<IAddQueue> _link;
        private List<Process> _wait;
        

        #region Implementation of IAddQueue

        public void Add(Process pro)
        {
            //if(pro.GetCpu()!=0) -> co Th cpu cua process = 0
            if(pro.GetCpu()==0)
            {
                foreach (var link in _link)
                {
                    link.Add(pro);
                }
            }else if(!pro.IsProcessing)
            {
                _processes.AddFirst(pro);
                pro.IsProcessing = true;
            }

            
        }

        public void AddLink(IAddQueue link)
        {
            _link.Add(link);
        }

        #endregion

        #region Implementation of IRunable
        public void PrintDebug()
        {
            Console.Write("\t\t queue");
            foreach (var process in _processes)
            {
                Console.Write("P{0},",process.Id);
            }
        }
        public void SendWait(Process pro)
        {
            _wait.Add(pro);
        }
        public void Send()
        {
            foreach (var process in _wait)
            {
                foreach (var addQueue in _link)
                {
                    addQueue.Add(process);
                }
            }
            _wait.Clear();
        }

        public void Run(object source, TickEventArgs e)
        {
            Send();
            var tick =  e.TickTime;
            const int t = 1;
            if(tick<1) return;
            if(_processes.Count==0) return;

            LinkedListNode<Process> processing=_processes.Last;

            
            _time--;
            processing.Value.DecCpu();
            AddTimeWait(processing.Value);
            
            if (processing.Value.GetCpu()==0)
            {
                
                Console.Write("{0}:P{1}",tick,processing.Value.Id);
                PrintDebug();Console.WriteLine();
                _time = _q;
                _processes.RemoveLast();
                processing.Value.IsProcessing = false;
                SendWait(processing.Value);
                //foreach (var  link in _link)
                //{
                //    link.Add(processing.Value);
                //}
                return;

            }

            if(_time==0)
            {
                Console.Write("{0}:P{1}", tick, processing.Value.Id);
                PrintDebug(); Console.WriteLine();
                _time = _q;
                _processes.RemoveLast();
                _processes.AddFirst(processing);
            }
            
            
        }

        #endregion
        public void AddTimeWait(Process processing)
        {
            foreach (var process in _processes)
            {
                if (process != processing)
                {
                    process.AddTimewait();
                }
            }
        }
        public Cpu(int q)
        {
             _q = q;// =3
            _time = q;
            _link = new List<IAddQueue>();
            _processes = new LinkedList<Process>();
            _wait = new List<Process>();
        }
    }
    
}
